<?php
/**
 * Created by PhpStorm.
 * User: ownfi
 * Date: 2017-04-17
 * Time: 21:11
 */

namespace App\Services\Impl;


use App\Common\Constant\Params;
use App\Models\MasterCash;
use App\Models\MasterFund;
use App\Models\MasterTradeLog;
use App\Models\MasterWallet;
use App\Models\MerchantTradeLog;
use App\Models\Order;
use App\Models\OrderComplain;
use App\Models\OrderRefund;
use App\Services\IMasterLogService;
use App\Services\IMerchantLogService;
use App\Services\IMerchantService;
use App\Services\IPayService;
use App\Services\ISystemService;
use App\Services\ISystemTaskService;
use App\Services\IWalletService;
use DB;
use Log;

class SystemTaskServiceImpl implements ISystemTaskService
{

    private $walletService;
    private $masterLogService;
    private $systemService;
    private $merchantLogService;
    private $merchantService;
    private $payService;

    /**
     * SystemTaskServiceImpl constructor.
     */
    public function __construct(IWalletService $walletService,IMasterLogService $masterLogService,ISystemService $systemService,
                                IMerchantLogService $merchantLogService,IMerchantService $merchantService,IPayService $payService)
    {
        $this->walletService = $walletService;
        $this->masterLogService = $masterLogService;
        $this->systemService = $systemService;
        $this->merchantLogService = $merchantLogService;
        $this->merchantService = $merchantService;
        $this->payService = $payService;
    }

    public function orderMoneyArrive($order_id)
    {
        $order = Order::find($order_id);
        if (!$order){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss order'));
            return false;
        }

        //生成师傅交易记录
        $trade_log = $this->masterLogService->orderMoneyArriveLog($order);
        if (!$trade_log){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss trade log'));
            return false;
        }

        //加上补款金额
        $amount = $order->master_money + $order->replenish_total;

        //系统钱包减去佣金（留下抽成），师傅钱包余额加上佣金
        $ret = $this->systemService->subtractBalance($trade_log->id,$order->master_id,Params::USER_TYPE_MASTER,$amount)
            && $this->walletService->raiseBalance($trade_log->id,$order->master_id,$amount);
        if (!$ret){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'balance update fail'));
            return false;
        }

        return $this->payService->handlePaymentSuccess($trade_log->trade_number);
    }

    public function orderRefundPay($refund_id,$amount)
    {
        $refund = OrderRefund::find($refund_id);
        if(!$refund){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss refund'));
            return false;
        }

        //生成商家交易记录
        $trade_log = $this->merchantLogService->orderRefundPayLog($refund,$amount);
        if (!$trade_log){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss trade log'));
            return false;
        }
        //系统钱包减去退款
        $ret = $this->systemService->subtractBalance($trade_log->id,$refund->order->merchant_id,Params::USER_TYPE_MERCHANT,$amount);
        if (!$ret){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'system subtract balance faill'));
            return false;
        }
        //商家余额或者直接退款到支付宝
        if ($refund->refund_method == Params::REFUND_METHOD_ORIGIN){//原路退还
            $pay_trade_log = MerchantTradeLog::where(['merchant_id'=>$refund->order->merchant_id,'type'=>Params::MERCHANT_TRADE_TYPE_ORDER,'status'=>Params::TRADE_STATUS_SUCCESS])
                ->whereRaw("find_in_set({$refund->order_id},order_number_list)")->first();
            if (!$pay_trade_log){
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss pay trade log'));
                return false;
            }
            if ($pay_trade_log->source == Params::TRADE_SOURCE_ALIPAY){
                if (!$pay_trade_log->alipay_no){
                    Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'pay trade log miss alipay_no'));
                    return false;
                }
                $this->payService->setPaymentMethod(Params::PAY_METHOD_ALIPAY);
                $ret = $this->payService->doRefund($trade_log->trade_number,$pay_trade_log->trade_number,$pay_trade_log->alipay_no,$amount);
            }else{//退款到商家余额
                $ret = $this->merchantService->raiseBalance($trade_log->id,$refund->order->merchant_id,$amount)
                    && $this->payService->handleMerchantPaymentSuccess($trade_log->trade_number);
            }
        }else{//退款到商家余额
            $ret = $this->merchantService->raiseBalance($trade_log->id,$refund->order->merchant_id,$amount)
            && $this->payService->handleMerchantPaymentSuccess($trade_log->trade_number);
        }

        if (!$ret){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'refund pay faill'));
            return false;
        }

        //部分退款的情况下，订单剩余的钱扣除平台抽成要打入师傅钱包余额
        if ($refund->master_remain){
            //生成师傅交易记录
            $trade_log = $this->masterLogService->orderRefundPayLog($refund,$refund->master_remain);
            if (!$trade_log){
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'master refund pay log fail'));
                return false;
            }
            $ret = $this->walletService->raiseBalance($trade_log->id,$refund->order->master_id,$refund->master_remain);
        }

        return $ret;
    }

    public function masterCashPay($cash_id)
    {
        $cash = MasterCash::find($cash_id);
        if(!$cash){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss cash'));
            return false;
        }
        if (empty($cash->alipay_name) || empty($cash->alipay_account)){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss alipay account'));
            return false;
        }
        $wallet = MasterWallet::where('master_id',$cash->master_id)->first();
        if(!$wallet){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss master wallet'));
            return false;
        }
        $trade_log = MasterTradeLog::where(['type'=>Params::TRADE_TYPE_CASH,'order_number'=>$cash->id])->first();
        if(!$trade_log){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss trade log'));
            return false;
        }
        if ($trade_log->status == Params::TRADE_STATUS_WAITING){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'trade log still waiting'));
            return false;
        }

        //没有缴纳质保金的师傅，在提现的时候要收取2%的服务费
        if (!$wallet->assure_fund){
            $system_earn = $cash->amount*config('common.nofund_earn_percent_per_cash');
            //如果收取的服务费少于0.01，就不收了
            if ($system_earn < 0.01){
                $amount = $cash->amount;
            }else{
                $amount = $cash->amount - $system_earn;
                $amountf=sprintf("%.2f",$amount);//格式化提现金额只保留两位小数.
                //$amountf=round($amount,2);
            }
        }else{
            $amount = $cash->amount;
        }

        $this->payService->setPaymentMethod(Params::PAY_METHOD_ALIPAY);
        $ret = $this->payService->doCash($trade_log->trade_number,$cash->alipay_name,$cash->alipay_account,$amountf);
        if(!$ret) {
            //如果转帐失败则进行标记
            $data = [
                'status'=> Params::MASTER_CASH_ALIPAY_FAIL,
            ];
            $result = MasterCash::where(['id'=>$cash->id])->update($data);
            if(!$result) {
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'alipay fail MasterCash update fail'));
            }
        }
        return $ret;
    }

    public function AssureFundReturn($refund_id)
    {
        $fund = MasterFund::find($refund_id);
        if(!$fund){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss fund'));
            return false;
        }
        if (empty($fund->alipay_name) || empty($fund->alipay_account)){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss alipay account'));
            return false;
        }
        $trade_log = MasterTradeLog::where(['type'=>Params::TRADE_TYPE_RETURN_ASSURE,'order_number'=>$fund->id])->first();
        if(!$trade_log){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss trade log'));
            return false;
        }
        if ($trade_log->status == Params::TRADE_STATUS_WAITING){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'trade log still waiting'));
            return false;
        }

        $this->payService->setPaymentMethod(Params::PAY_METHOD_ALIPAY);
        $ret = $this->payService->doReturnFund($trade_log->trade_number,$fund->alipay_name,$fund->alipay_account,$fund->amount);
        if(!$ret){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'payer return assure fund fail'));
            return false;
        }

        return $this->systemService->subtractBalance($trade_log->id,$fund->master_id,Params::USER_TYPE_MASTER,$fund->amount);
    }

    public function complainPunish($complain_id, $amount)
    {
        $complain = OrderComplain::find($complain_id);
        if(!$complain){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss complain'));
            return false;
        }
        $trade_log = $this->masterLogService->masterPunishLog($complain->order,$amount);
        if (!$trade_log){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'punish trade log create fail'));
            return false;
        }

        $ret = resolve(IWalletService::class)->punish($trade_log->id,$complain->order->master_id,$amount);
        if (!$ret){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'wallet punish fail'));
            return false;
        }

        return $this->payService->handlePaymentSuccess($trade_log->trade_number);
    }


}